<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">
	<title>Find Broken Links </title>
	<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.1.0.js"></script>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
	<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
	<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
	<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.min.css">
<style type="text/css">
.section{margin-top:10px;padding:5px;background-color:#e1e1e1;color:#000;font-size:15px;}
textarea{resize: none;}
.invalid{background-color:#ddd;}
.glyphicon-ok{color:green;}
.glyphicon-remove{color:red;}
.glyphicon-warning-sign{color:orange;}
a{cursor:pointer;}
</style> 
</head>
<body>
<div class="container">
	<div class="row clearfix">
		<div class="col-md-12 column">
			<h2> Find all anchor tags.<br></h2><hr>
			<div class="row clearfix">
				<div class="col-md-12 column section">
					<div class="col-md-6">
					<label for="pattern">Pattern</label>
					<input class="form-control" id="pattern" data-bind="value:regexPattern, valueUpdate:'afterkeydown'" name="regexPattern" placeholder="Enter Your Pattern Here."><hr>
					<label for="stringToTest">String To Test</label>
					<textarea class="form-control" autofocus id="stringToTest" data-bind="value:stringToTest, valueUpdate:'afterkeydown'" name="stringToTest" placeholder="Enter your test string here."></textarea><hr>
					<label for="baseurl">Base URL</label>
					<input class="form-control" id="baseurl" data-bind="value:baseurl, valueUpdate:'input'" name="baseurl" required placeholder="Enter Base URL for relative links.">			
					</div>
					<div class="col-md-6">
					<label> Select a scheme</label><input  id="http" type="radio" data-bind="checked:scheme,valueUpdate:'input'" name="scheme" value="http://"><label for="http">HTTP</label>
					<input   type="radio" data-bind="checked:scheme,valueUpdate:'input'" id="https" name="scheme" value="https://"><label for="https">HTTPS</label><hr>
					
					<input  id="hyperlinks" type="radio" data-bind="checked:regexPattern" value="href=[&quot;|'].*?[&quot;|']"><label for="hyperlinks">Hyperlinks</label>
					<input  id="urls" type="radio" data-bind="checked:regexPattern" value="http.*"><label for="urls">URL's</label><hr>
					<input id="testall" class="btn btn-success" type="button" value="Test All	" onclick="return testAll(1)"/>
					<div ><p class="error " data-bind="html:errorMsg,css:'invalid'" id="error-message"></p></div>
					</div>
				</div>
			</div>
		</div>
		<div class="col-md-12 column  ">
			<br>
			<div id="matches" data-bind="highlightedText:{text:stringToTest, matches: regexExecResult()}">
			</div>
		</div>
	</div>
	<div class="row clearfix ">
		<div class="col-md-12 column  ">
			<hr>
			<div class="col-md-6">                     
			<p>Designed By Santosh J.</p>
			</div>
			<div class="col-md-6">                     
			<p>Finds all href links in a page.</p>
			</div>
		</div>
	</div>
</div>
		<script type="text/javascript">
		$(document).ready(function(){
		$('#testall').hide();
		matched_arr= new Array();
		css_class=new String();
		invalid=new String();
			ko.bindingHandlers.highlightedText= { 
				update: function(element, valueAccessor) {
			        var options = valueAccessor();
			        var originalText = ko.utils.unwrapObservable(options.text);
			        var matches = ko.utils.unwrapObservable(options.matches);
			        if (matches && matches.length==0 ){
			        	element.innerHTML = originalText;  //return? 	
			        }
			        else  
			        { 
			        	var highlightedString="", startPos=0, replacement="";matched_arr.length=0; 
			        	for (var i=0; i < matches.length; i++){
							type= new String();
							type="\" style=\"color:#f0f;\">Unknown</i>";
							var valid_url=new RegExp("(http|https)://[A-Za-z0-9-]+(.[A-Za-z0-9-]+)*(.[A-Za-z]{2,})");
							if(valid_url.test(matches[i].matchedText))
							 {css_class=" "; invalid="valid";}
							else { css_class="glyphicon ";  invalid="invalid";}//for valid urls
							var css_type=new RegExp(".*css$");//for css files
							if(css_type.test(matches[i].matchedText))
							{type="\" style=\"color:#00f;\">css</i>";}
							var xml_type=new RegExp(".*xml$");//for xml files
							if(xml_type.test(matches[i].matchedText))
							{type="\" style=\"color:#f00;\">xml</i>";}												
							var pdf_type=new RegExp(".*pdf$");//for pdf files
							if(pdf_type.test(matches[i].matchedText))
							{type="\" style=\"color:blue;\">pdf</i>";}				
							var html_type=new RegExp(".*html$|.*htm$");//for html files
							if(html_type.test(matches[i].matchedText))
							{type="\" style=\"color:blue;\">html</i>";}
							var j=i+1;// for index purpose
			        		replacement ='<div class=" list-group-item '+invalid+'" id="div'+j+'" ><div class="label label-primary pull-left">&nbsp;'+ j +'</div>&nbsp;' + '<a class="col-md-8"id="'+j+'"   onclick="this.disabled=true;return testIt('+j+')" target="_blank" title="'+matches[i].matchedText+'"/>' + matches[i].matchedText.slice(0,90) + '</a><button type="button"  class="btn-xs btn-primary pull-right col-md-1" onclick="window.alert(\''+matches[i].matchedText+'\')"style="width: 45px;">Copy</button> <span class="col-md-1 pull-right">&nbsp;&nbsp;'+invalid+'&nbsp;</span> <i class="col-md-1 pull-right '+css_class+type+'</div>';
			        		var myString = originalText.substring(0,0) +replacement;
			        		highlightedString += myString; 
							matched_arr[i]=matches[i].matchedText;
			        	}     
			        	element.innerHTML = highlightedString;	
						if(matches.length>10)
							$('#testall').show();
						else if(matches.length<10)
							$('#testall').hide();
			        }
				}  						
			}	
			function ViewModel() {
			// this.match= [new Open()];
				var self = this; 
				//input fields
				self.regexPattern = ko.observable("href=[\"|'].*?[\"|']"); 
				self.stringToTest = ko.observable(""); 
				self.scheme=ko.observable("http://");
				self.baseurl=ko.observable("www.cisco.com");
				
				//options
				self.optionGlobal = ko.observable(true);
				self.optionCase = ko.observable(true); 
				self.optionLines = ko.observable(false);

				//options helper
				self.regexOptions = ko.computed(function () { 
					return (self.optionGlobal(true) ? "g" : "") + 
							(self.optionCase(true) ? "i" : "") + 
							(self.optionLines(false) ? "m" : ""); 
				}); 
				self.errorMsg = ko.observable(); 
				self.okToRunRegex = function() { 
					if (!self.regexPattern() || !self.stringToTest()) {	return false;}
					return true; 
				}
				//output 
				self.regexExecResult = ko.observableArray(); 
				self.processRegex = ko.computed(function() { 
					if (!self.okToRunRegex()) {
						return false; 
					}
					try { 
						var pattern = new RegExp(self.regexPattern().trim(), self.regexOptions());
						self.errorMsg(""); 
						var execMatch, matches=[]; 
						//self.regexExecResult([]); 
						while (execMatch = pattern.exec(self.stringToTest())){
						var patt=new RegExp("href=\"//");//to find href links containing protocol url
						var patt1 = new RegExp("href=\"");// to find href links containing normal url
						var patt2=new RegExp("href='");//to find href links like href='
						var patt3=new RegExp("^/");// to find relative url
						var patt3a=new RegExp(" /");// to find relative url starting with space
						var patt4=new RegExp("\"");// to remove last qoute
						var patt5=new RegExp("'");// to remove  single quote
						var patt6=new RegExp("href=\"\"|href=\"javascript|href=\"#|href=\"mailto|href=\"\{|href=[\"|'][a-zA-Z|-|_]*.html|href=[\"|'][a-zA-Z|-|_]*?[\"|']|#");// href links like href="", javascript , #, mailto,{0}, only html page
						var patt7=new RegExp("href=\"www");// href links like href=""
						for(i=0;i<execMatch.length;i++)
						{ //code for matching different kind of urls
							if(patt6.test(execMatch[i]))
							continue;
							if(patt.test(self.stringToTest()) )
							execMatch[i] = execMatch[i].replace("href=\"//",self.scheme());
							if(patt7.test(execMatch[i])) 
							execMatch[i] = execMatch[i].replace("href=\"",self.scheme());
							if(patt1.test(execMatch[i]))
							execMatch[i] = execMatch[i].replace("href=\"", "");
							if(patt2.test(execMatch[i]))//remove 
							execMatch[i] = execMatch[i].replace("href='", "");		
							if(patt3.test(execMatch[i]))
							execMatch[i] = execMatch[i].replace("/", self.scheme()+self.baseurl()+"/");
							if(patt3a.test(execMatch[i]))
							execMatch[i] = execMatch[i].replace(" /", self.scheme()+self.baseurl()+"/");
							if(patt4.test(execMatch[i])) 
							execMatch[i] = execMatch[i].replace("\"", "");
							if(patt5.test(execMatch[i])) 
							execMatch[i] = execMatch[i].replace("'", "");
							url=execMatch[i];							
							matches.push({matchedText: execMatch[i], index: execMatch.index});
						}
						}
						self.regexExecResult(matches);
					}
					catch(err)
					{self.errorMsg(err.message); }
				});			
			}
			ko.applyBindings(new ViewModel());

			});
						// to test individual link
			function testIt(num)
			{
			id="#"+num;
			status=new String();
			content=new String();
			url=$(id).attr('title');
			spanid="#span"+num;
			$(id).removeAttr('onclick');
			$(id).append('<span id="span'+num+'" class="span "> </span>');
			$(spanid).addClass('fa fa-spinner fa-spin pull-right');
			$.getJSON('http://whateverorigin.org/get?url=' + encodeURIComponent(url) + '&callback=?', function(data){ 
			$(spanid).removeClass('fa fa-spinner fa-spin pull-right');
			status=data.status.http_code;
			console.log(num,'.(',status,')',url);
			if(status=="200")
			{
			$(spanid).addClass(' glyphicon glyphicon-ok pull-right');}
			if(status=="404")
			{
			$(spanid).addClass(' glyphicon glyphicon-remove pull-right');}
			if(status=="302")
			{				
			$(id).append('<span class=" glyphicon glyphicon-warning-sign pull-right"> </span>');}
			$(id).attr("href", url);	
			});	
			}
			//to test all links at a time
			function testAll(num)
			{
			id="#"+num;
			status=new String();
			content=new String();
			url=$(id).attr('title');
			spanid="#span"+num;
			$(id).removeAttr('onclick');
			$(id).append('<i id="span'+num+'" class="span "> </i>');
			$(spanid).addClass('fa  fa-spinner fa-spin pull-right');
			$.getJSON('http://whateverorigin.org/get?url=' + encodeURIComponent(url) + '&callback=?', function(data){ 
			$(spanid).removeClass('fa  fa-spinner fa-spin pull-right');
			status=data.status.http_code;
			console.log(num,'.(',status,')',url);
			if(status=="200")
			{
			$(spanid).addClass(' glyphicon glyphicon-ok pull-right');}
			if(status=="404")
			{
			$(spanid).addClass(' glyphicon glyphicon-remove pull-right');}
			if(status=="302")
			{				
			$(id).append('<span class=" glyphicon glyphicon-warning-sign pull-right"> </span>');}
			$(id).attr("href", url);	
			if(num<matched_arr.length)
			{
			num++;
			testAll(num);
			}
			});	
			}
</script> 
	</body>
</html>